#ifndef AXISCONFIG_H
#define AXISCONFIG_H

#include "commonmethod.h"
#include "configManager/configobject.h"
#include "enumhelper.h"
#include "scmotion_global.h"

class SCMOTIONSHARED_EXPORT AxisConfig : public ConfigObject
{
    Q_OBJECT

    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(bool jogMovable READ jogMovable WRITE setJogMovable NOTIFY jogMovableChanged)
    Q_PROPERTY(double velocityRatio READ velocityRatio WRITE setVelocityRatio NOTIFY velocityRatioChanged)
    Q_PROPERTY(bool isBelt READ isBelt WRITE setIsBelt NOTIFY isBeltChanged)
    Q_PROPERTY(QString homeExecutor READ homeExecutor WRITE setHomeExecutor NOTIFY homeExecutorChanged)
    Q_PROPERTY(QString startHomeDoName READ startHomeDoName WRITE setStartHomeDoName NOTIFY startHomeDoNameChanged)
    Q_PROPERTY(QString homeDoneDiName READ homeDoneDiName WRITE setHomeDoneDiName NOTIFY homeDoneDiNameChanged)
    Q_PROPERTY(double homeOffsetBetweenDriverAndController READ homeOffsetBetweenDriverAndController WRITE
                   setHomeOffsetBetweenDriverAndController NOTIFY homeOffsetBetweenDriverAndControllerChanged)

public:
    Q_INVOKABLE AxisConfig(QObject *parent = nullptr) : ConfigObject(parent)
    {
        setReadOnlyProperty("name");
        setOptionalProperty("homeExecutor", toVariantList(HomeExecutorEnumInfo().names()));
        init();
    }

    void setOptionalIOName(QVariantList diNames, QVariantList doNames)
    {
        diNames.append("");
        doNames.append("");
        setOptionalProperty("startHomeDoName", doNames);
        setOptionalProperty("homeDoneDiName", diNames);
        init();
    }

    enum HomeExecutor
    {
        Controller,
        Driver,
        DriverThenController
    };
    Q_ENUM(HomeExecutor)

    static EnumHelper<HomeExecutor> &HomeExecutorEnumInfo()
    {
        static EnumHelper<HomeExecutor> instance(staticMetaObject, "HomeExecutor");
        return instance;
    }

    double velocityRatio() const
    {
        return m_velocityRatio;
    }

    QString name() const
    {
        return m_name;
    }

    bool isBelt() const
    {
        return m_isBelt;
    }

    QString homeExecutor() const
    {
        return m_homeExecutor;
    }

    QString startHomeDoName() const
    {
        return m_startHomeDoName;
    }

    QString homeDoneDiName() const
    {
        return m_homeDoneDiName;
    }

    double homeOffsetBetweenDriverAndController() const
    {
        return m_homeOffsetBetweenDriverAndController;
    }

    bool jogMovable() const
    {
        return m_jogMovable;
    }

public slots:
    void setVelocityRatio(double velocityRatio)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_velocityRatio, velocityRatio))
            return;
        if (velocityRatio <= 0 || velocityRatio > 1)
        {
            qCritical("Velocity ratio should be in range (0, 1]! Value: %f", velocityRatio);
            return;
        }

        m_velocityRatio = velocityRatio;
        emit velocityRatioChanged(m_velocityRatio);
    }

    void setName(QString name)
    {
        if (m_name == name)
            return;

        m_name = name;
        emit nameChanged(m_name);
    }

    void setIsBelt(bool isBelt)
    {
        if (m_isBelt == isBelt)
            return;

        m_isBelt = isBelt;
        emit isBeltChanged(m_isBelt);
    }

    void setHomeExecutor(QString homeExecutor)
    {
        if (m_homeExecutor == homeExecutor)
            return;

        m_homeExecutor = homeExecutor;
        emit homeExecutorChanged(m_homeExecutor);
    }

    void setStartHomeDoName(QString startHomeDoName)
    {
        if (m_startHomeDoName == startHomeDoName)
            return;

        m_startHomeDoName = startHomeDoName;
        emit startHomeDoNameChanged(m_startHomeDoName);
    }

    void setHomeDoneDiName(QString homeDoneDiName)
    {
        if (m_homeDoneDiName == homeDoneDiName)
            return;

        m_homeDoneDiName = homeDoneDiName;
        emit homeDoneDiNameChanged(m_homeDoneDiName);
    }

    void setHomeOffsetBetweenDriverAndController(double homeOffsetBetweenDriverAndController)
    {
        //        qWarning("Floating point comparison needs context sanity check");
        if (qFuzzyCompare(m_homeOffsetBetweenDriverAndController, homeOffsetBetweenDriverAndController))
            return;

        m_homeOffsetBetweenDriverAndController = homeOffsetBetweenDriverAndController;
        emit homeOffsetBetweenDriverAndControllerChanged(m_homeOffsetBetweenDriverAndController);
    }

    void setJogMovable(bool jogMovable)
    {
        if (m_jogMovable == jogMovable)
            return;

        m_jogMovable = jogMovable;
        emit jogMovableChanged(m_jogMovable);
    }

signals:
    void velocityRatioChanged(double velocityRatio);

    void nameChanged(QString name);

    void isBeltChanged(bool isBelt);

    void homeExecutorChanged(QString homeExecutor);

    void startHomeDoNameChanged(QString startHomeDoName);

    void homeDoneDiNameChanged(QString homeDoneDiName);

    void homeOffsetBetweenDriverAndControllerChanged(double homeOffsetBetweenDriverAndController);

    void jogMovableChanged(bool jogMovable);

private:
    double m_velocityRatio = 0.5;
    QString m_name;
    bool m_isBelt = false;
    QString m_homeExecutor = "Controller";
    QString m_startHomeDoName;
    QString m_homeDoneDiName;
    double m_homeOffsetBetweenDriverAndController = 0;
    bool m_jogMovable = true;
};

#endif    // AXISCONFIG_H
